package output.database;

import java.sql.*;

import java.util.*;

public class JavaDbManager {

	public static String FRAMEWORK = "embedded";
	public static String DRIVER = "org.apache.derby.jdbc.EmbeddedDriver";
	public static String PROTOCOL = "jdbc:derby:";
	public static boolean AUTO_COMMIT = false;
	private Connection conn;
	private String dbName;
	
	public String getName() {
		return dbName;
	}
	
	public Connection getConnection() {
		return conn;
	}

	public JavaDbManager(String dbName) {
		/* load the desired JDBC driver */
		loadDriver();
		this.dbName = dbName;
		Properties props = new Properties(); // connection properties

		try {
			conn = DriverManager.getConnection(PROTOCOL + dbName
					+ ";create=true", props);
			// We want to control transactions manually. Autocommit is on by
			// default in JDBC.
			conn.setAutoCommit(AUTO_COMMIT);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public void kill(JavaDbManager db) {
		kill(db.getName());
	}
	
	public void kill(String dbName) {
		killPriv("jdbc:derby:" + dbName + ";shutdown=true");
	}

	public static void kill() {
		killPriv("jdbc:derby:;shutdown=true");
	}
	
	private static void killPriv(String conString) {
		if (FRAMEWORK.equals("embedded")) {
			try {
				DriverManager.getConnection(conString);
			} catch (SQLException se) {
				if (((se.getErrorCode() == 50000) && ("XJ015".equals(se
						.getSQLState())))) {
					// expected shutdown exception
				} else {
					System.err.println("Derby did not shut down normally");
					printSQLException(se);
				}
			}
		}
	}

	/**
	 * Loads the appropriate JDBC driver for this environment/framework. For
	 * example, if we are in an embedded environment, we load Derby's embedded
	 * Driver, <code>org.apache.derby.jdbc.EmbeddedDriver</code>.
	 */
	private void loadDriver() {
		try {
			Class.forName(DRIVER).newInstance();
		} catch (ClassNotFoundException cnfe) {
			System.err.println("\nUnable to load the JDBC driver " + DRIVER);
			System.err.println("Please check your CLASSPATH.");
			cnfe.printStackTrace(System.err);
		} catch (InstantiationException ie) {
			System.err.println("\nUnable to instantiate the JDBC driver "
					+ DRIVER);
			ie.printStackTrace(System.err);
		} catch (IllegalAccessException iae) {
			System.err.println("\nNot allowed to access the JDBC driver "
					+ DRIVER);
			iae.printStackTrace(System.err);
		}
	}

	/**
	 * Prints details of an SQLException chain to <code>System.err</code>.
	 * Details included are SQL State, Error code, Exception message.
	 * 
	 * @param e
	 *            the SQLException from which to print details.
	 */
	public static void printSQLException(SQLException e) {
		while (e != null) {
			System.err.println("\n----- SQLException -----");
			System.err.println("  SQL State:  " + e.getSQLState());
			System.err.println("  Error Code: " + e.getErrorCode());
			System.err.println("  Message:    " + e.getMessage());
			e = e.getNextException();
		}
	}
}
